package zero.tech.games.pdk.work.sync;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.alibaba.fastjson.JSONObject;

import zero.tech.core.ZeroContext;
import zero.tech.core.data.KeyVal;
import zero.tech.core.util.StringHelper;
import zero.tech.core.work.AynWork;
import zero.tech.core.work.WorkManager;
import zero.tech.games.common.WaterMode;
import zero.tech.games.entity.games.Club;
import zero.tech.games.logic.common.Room;
import zero.tech.games.logic.data.panel.SmallPanel;
import zero.tech.games.logic.service.api.ILogicService;
import zero.tech.games.pdk.data.PdkBigPanel;
import zero.tech.games.pdk.data.PdkConfig;
import zero.tech.games.pdk.data.PdkRoomCache;
import zero.tech.games.pdk.data.PdkSmallPanel;
import zero.tech.games.pdk.data.entity.PlayerBigCal;
import zero.tech.games.pdk.data.entity.PlayerSmallCal;
import zero.tech.games.pdk.work.queue.AfterGameOverCalculateQueueWork;
import zero.tech.wsnet.controller.LogicController;

public class GameOverCalculateSyncWork extends AynWork{
	private Room room;
	private int source;
	@Override
	public void init(Object... objs) throws Exception {
		room=(Room) objs[0];
		source=(int) objs[1];
	}

	@Override
	public void run() {
		synchronized (room.getTransform_lock()) {
			bigCalculate(room);
			Club club=room.getClub();
			if(club!=null) {
				//结算代码在此处
				roomTransform(room);
			}else {
				//结算砖石
				diamondTransform(room);
			}
			WorkManager.getManager().submit(AfterGameOverCalculateQueueWork.class,room,source);
		}
	}

	private void diamondTransform(Room room) {
		PdkConfig pdkConfig = (PdkConfig) room.getGameConfig();
		int water_mode=pdkConfig.getWater_mode();
		long water_num=pdkConfig.getWater_num();
		Map<Integer,LogicController> controllers=room.getAllControllers();
		Map<Integer,Long> diamondchangemap=new HashMap<>();
		if(water_mode==WaterMode.AA) {
			for(LogicController logicController:controllers.values()) {
				int uid=logicController.getId();
				diamondchangemap.put(uid, -water_num);
			}
		}
		if(!diamondchangemap.isEmpty()) {
			ILogicService logicService=ZeroContext.getInstance(ILogicService.class);
			logicService.gameUpdateDiamondBatch(room, diamondchangemap);
		}
	}

	private Map<Integer, Integer> scoreBird(Room room) {
		Map<Integer,Integer> score_bird=new HashMap<>();//某人赢了多少鸟分
		Map<Integer, Integer> score_map=new HashMap<>();//某人所有小局总积分计算大赢家
		PdkRoomCache pdkRoomCache = (PdkRoomCache) room.getRoomCache();
		Map<Integer, SmallPanel> smallpanels=pdkRoomCache.getSmallPanels();
		//计算所有小局总分数
		for(SmallPanel smallPanel:smallpanels.values()) {
			PdkSmallPanel pdkSmallPanel = (PdkSmallPanel) smallPanel;
			List<PlayerSmallCal> playerSmallCals=pdkSmallPanel.getPlayerCals();
			for(PlayerSmallCal playerSmallCal:playerSmallCals) {
				int uid=playerSmallCal.getSimpleUser().getUid();
				int cur_win_score=playerSmallCal.getCur_win_score();
				if(!score_map.containsKey(uid)) {
					score_map.put(uid,cur_win_score);
				}else {
					int old=score_map.get(uid);
					score_map.put(uid, old+cur_win_score);
				}
			}
		}
		Map<Integer,Integer> birds=pdkRoomCache.getBirds();
		//积分最高者为大赢家
		List<KeyVal<Integer, Integer>> list=StringHelper.parseMapToList(score_map);
		if(!list.isEmpty()) {
			Collections.sort(list,new Comparator<KeyVal<Integer, Integer>>() {

				@Override
				public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
					return o2.getV()-o1.getV();
				}
			});
			
			if(list.size()==2) {
				//2人局
				int one_uid=list.get(0).getK();
				int one_score=list.get(0).getV();
				int one_bird=birds.get(one_uid)==null?0:birds.get(one_uid);
				int two_uid=list.get(1).getK();
				int two_score=list.get(1).getV();
				int two_bird=birds.get(two_uid)==null?0:birds.get(two_uid);
				if(one_score==two_score) {
					score_bird.put(one_uid, 0);
					score_bird.put(two_uid, 0);
				}else {
					score_bird.put(one_uid, one_bird+two_bird);
					score_bird.put(two_uid, -(one_bird+two_bird));
				}
			}else if(list.size()==3) {
				//3人局
				int one_uid=list.get(0).getK();
				int one_score=list.get(0).getV();
				int one_bird=birds.get(one_uid)==null?0:birds.get(one_uid);
				int two_uid=list.get(1).getK();
				int two_score=list.get(1).getV();
				int two_bird=birds.get(two_uid)==null?0:birds.get(two_uid);
				int three_uid=list.get(2).getK();
				int three_score=list.get(2).getV();
				int three_bird=birds.get(three_uid)==null?0:birds.get(three_uid);
				if(one_score==two_score) {
					if(two_score==three_score) {
						//3人分数一样
						score_bird.put(one_uid, 0);
						score_bird.put(two_uid, 0);
						score_bird.put(three_uid, 0);
					}else {
						//两人并列第一名赢第三名
						score_bird.put(one_uid, one_bird+three_bird);
						score_bird.put(two_uid, two_bird+three_bird);
						score_bird.put(three_uid, -((one_bird+three_bird)+(two_bird+three_bird)));
					}
				}else {
					//第二名第三名输第一名
					score_bird.put(one_uid, (one_bird+two_bird)+(one_bird+three_bird));
					score_bird.put(two_uid, -(one_bird+two_bird));
					score_bird.put(three_uid, -(one_bird+three_bird));
				}
			}
		}
		return score_bird;
	}
	
	private void roomTransform(Room room) {
		PdkConfig pdkConfig = (PdkConfig) room.getGameConfig();
		int water_mode=pdkConfig.getWater_mode();
		long water_num=pdkConfig.getWater_num();
		long free_water_num=pdkConfig.getFree_water_num();
		Map<Integer,Long> watermap=new HashMap<>();
		Map<Integer,Long> goldchangemap=new HashMap<>();
		
		Map<Integer,Long> winmap=new HashMap<>();
		Map<Integer,LogicController> controllers=room.getAllControllers();
		List<Integer> uids=new ArrayList<Integer>();
		for(LogicController logicController:controllers.values()) {
			int uid=logicController.getId();
			long gold_from_gate=logicController.getGold_from_gate();
			long gold=logicController.getGold();
			long win=gold-gold_from_gate;
			winmap.put(uid, win);
			uids.add(uid);
		}
		if(water_mode==WaterMode.WINER) {
			//大赢家抽水
			List<KeyVal<Integer, Long>>  list=StringHelper.parseMapToList(winmap);
			Collections.sort(list,new Comparator<KeyVal<Integer, Long>>() {
				@Override
				public int compare(KeyVal<Integer, Long> o1, KeyVal<Integer, Long> o2) {
					return (int) (o2.getV()-o1.getV());
				}
			});
			int bigwinner_uid=list.get(0).getK();
			long win=list.get(0).getV();
			if(win>free_water_num) {
				//超出面抽水限额,需要进行抽水
				watermap.put(bigwinner_uid, water_num);
			}
		}else {
			//AA抽水
			for(LogicController logicController:controllers.values()) {
				int uid=logicController.getId();
				watermap.put(uid, water_num);
			}
		}
		//除去抽水
		for(LogicController logicController:controllers.values()) {
			int uid=logicController.getId();
			long gold_from_gate=logicController.getGold_from_gate();
			long gold=logicController.getGold();
			if(watermap.containsKey(uid)) {
				gold=gold-watermap.get(uid);
			}
			logicController.setGold(gold);
			long change=gold-gold_from_gate;
			goldchangemap.put(uid, change);
		}
		
		if(water_mode==WaterMode.WINER) {
			//计算平分业绩
			long total=0;
			for(Entry<Integer,Long> entry:watermap.entrySet()) {
				total+=entry.getValue();
			}
			watermap.clear();
			long pinjun=total/controllers.size();
			for(LogicController logicController:controllers.values()) {
				watermap.put(logicController.getId(), pinjun);
			}
		}
		
		
		
		String joiners=JSONObject.toJSONString(uids);
		ILogicService logicService=ZeroContext.getInstance(ILogicService.class);
		logicService.gameUpdateBatch(room, joiners, null, goldchangemap, watermap);
	}

	private void bigCalculate(Room room) {
		//计算大鸟输赢
		PdkConfig pdkConfig = (PdkConfig) room.getGameConfig();
		long base_score=pdkConfig.getBase_score();
		Map<Integer, Integer> bird_win_score=scoreBird(room);
		for(Entry<Integer,Integer> entry:bird_win_score.entrySet()) {
			int uid=entry.getKey();
			int bird_score=entry.getValue();
			LogicController logicController = room.getAllControllers().get(uid);
			long old_gold=logicController.getGold();
			long old_win=logicController.getWin();
			long win=bird_score*base_score;
			logicController.setWin(old_win+win);
			logicController.setGold(old_gold+win);
		}
		
		
		PdkBigPanel pdkBigPanel = new PdkBigPanel();
		Map<Integer,Integer> lose_times=new HashMap<>();
		Map<Integer,Integer> win_times=new HashMap<>();
		Map<Integer,Integer> zhadan_times=new HashMap<>();
		Map<Integer,Integer> total_win_score=new HashMap<>();
		Map<Integer,Integer> danju_zuigao=new HashMap<>();
		Map<Integer,Long> total_win_gold=new HashMap<>();
		PdkRoomCache pdkRoomCache = (PdkRoomCache) room.getRoomCache();
		for(SmallPanel smallPanel:pdkRoomCache.getSmallPanels().values()) {
			PdkSmallPanel pdkSmallPanel = (PdkSmallPanel) smallPanel;
			List<PlayerSmallCal> playerSmallCals=pdkSmallPanel.getPlayerCals();
			for(PlayerSmallCal playerSmallCal:playerSmallCals) {
				int uid=playerSmallCal.getSimpleUser().getUid();
				int cur_win_score=playerSmallCal.getCur_win_score();
				int zhadan_count=playerSmallCal.getZhadan_count();
				long cur_win_gold=playerSmallCal.getCur_win_gold();
				if(cur_win_gold!=0) {
					if(!total_win_gold.containsKey(uid)) {
						total_win_gold.put(uid, cur_win_gold);//当前总输赢
					}else {
						long old=total_win_gold.get(uid);
						total_win_gold.put(uid, old+cur_win_gold);
					}
				}
				if(cur_win_score<0) {
					if(!lose_times.containsKey(uid)) {
						lose_times.put(uid, 1);//输局数+1
					}else {
						int old=lose_times.get(uid);
						lose_times.put(uid, old+1);
					}
				}
				if(cur_win_score>0) {
					if(!win_times.containsKey(uid)) {
						win_times.put(uid, 1);//赢局数+1
					}else {
						int old=win_times.get(uid);
						win_times.put(uid, old+1);
					}
				}
				if(zhadan_count>0) {
					if(!zhadan_times.containsKey(uid)) {
						zhadan_times.put(uid, zhadan_count);//炸弹数量
					}else {
						int old=zhadan_times.get(uid);
						zhadan_times.put(uid, old+zhadan_count);
					}
				}
				if(cur_win_score!=0) {
					if(!total_win_score.containsKey(uid)) {
						total_win_score.put(uid, cur_win_score);//赢总分
					}else {
						int old=total_win_score.get(uid);
						total_win_score.put(uid, old+cur_win_score);
					}
					
					if(!danju_zuigao.containsKey(uid)) {
						danju_zuigao.put(uid,cur_win_score);
					}else {
						int old=danju_zuigao.get(uid);
						if(cur_win_score>old) {
							danju_zuigao.put(uid, cur_win_score);
						}
					}
				}
				
			}
		}
		
		for(LogicController logicController:room.getAllControllers().values()) {
			int uid=logicController.getId();
			int total_score=total_win_score.get(uid)==null?0:total_win_score.get(uid);
			long total_gold=total_win_gold.get(uid)==null?0:total_win_gold.get(uid);
			int bird_score=bird_win_score.get(uid)==null?0:bird_win_score.get(uid);
			long bird_gold=bird_score*base_score;
			total_score+=bird_score;
			total_gold+=bird_gold;
			PlayerBigCal playerBigCal=new PlayerBigCal();
			playerBigCal.setSimpleUser(logicController.getSimpleUser());
			playerBigCal.setLose_times(lose_times.get(uid)==null?0:lose_times.get(uid));
			playerBigCal.setWin_times(win_times.get(uid)==null?0:win_times.get(uid));
			playerBigCal.setZhadan_count(zhadan_times.get(uid)==null?0:zhadan_times.get(uid));
			playerBigCal.setDanju_max_score(danju_zuigao.get(uid)==null?0:danju_zuigao.get(uid));
			playerBigCal.setTotal_win_score(total_score);
			playerBigCal.setBird_win_score(bird_win_score.get(uid)==null?0:bird_win_score.get(uid));
			playerBigCal.setTotal_win_gold(total_gold);
			playerBigCal.setLeft_gold(logicController.getGold());
			pdkBigPanel.getPlayerCals().add(playerBigCal);
		}
		
		
		pdkBigPanel.setGameOverTime(System.currentTimeMillis());
		pdkRoomCache.setBigPanel(pdkBigPanel);
	}

}
